package com.pdg.islandinterloper.clientstatehandlers;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.os.AsyncTask;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;

import com.pdg.islandinterloper.MainActivity;
import com.pdg.islandinterloper.R;
import com.pdg.islandinterloper.baseclasses.ClientStateHandlerBase;
import com.pdg.islandinterloper.database.objects.Profile;
import com.pdg.islandinterloper.database.objects.WorldPosition;
import com.pdg.islandinterloper.enums.ClientState;
import com.pdg.islandinterloper.exceptions.IslandPositionGenerationException;

public class CreateWorldClientStateHandler extends
		ClientStateHandlerBase<MainActivity> {
	
	class GenerateIslandPositionsTask extends AsyncTask<Profile,Integer,List<List<WorldPosition>>>{
		private static final int TRIES_COUNTER_INITIAL_VALUE = 0;
		private static final int TRIES_COUNTER_FAILURE_THRESHHOLD = 1000;
		
		private CreateWorldClientStateHandler client = null;
		public GenerateIslandPositionsTask(CreateWorldClientStateHandler theClient){
			setClient(theClient);
		}
		
		@Override
		protected void onPreExecute(){
			
		}

		@Override
		protected List<List<WorldPosition>> doInBackground(Profile... theProfiles) {
			List<List<WorldPosition>> theResult = new ArrayList<List<WorldPosition>>();
			for(Profile theProfile: theProfiles){
				try {
					theResult.add(generateIslandPositionsForProfile(theProfile));
				} catch (IslandPositionGenerationException e) {
					theResult.add(null);
				}
				if(isCancelled()){
					return null; 
				}
			}
			return theResult;
		}
		
		@Override
		protected void onCancelled(List<List<WorldPosition>> theResult){
			
		}

		@Override
		protected void onPostExecute(List<List<WorldPosition>> theResult){
			
		}

		private List<WorldPosition> generateIslandPositionsForProfile(
				Profile theProfile) throws IslandPositionGenerationException {
			List<WorldPosition> theResult = new ArrayList<WorldPosition>();
			Integer theIslandCount = theProfile.getIslandCount();
			Random theRandom = new Random();
			while(theResult.size()<theIslandCount){
				if(isCancelled()){
					return null; 
				}
				publishProgress(theResult.size());
				WorldPosition theCandidate = null;
				int theCounter = TRIES_COUNTER_INITIAL_VALUE;
				boolean done = false;
				do{
					theCandidate = new WorldPosition(theRandom.nextDouble()*theProfile.getWorldWidth(),theRandom.nextDouble()*theProfile.getWorldHeight());
					double theMinimumDistance = Double.MAX_VALUE;
					for(WorldPosition thePosition:theResult){
						double theDistance = thePosition.getWorldShapeDistance(theCandidate, theProfile);
						if(theDistance<theMinimumDistance){
							theMinimumDistance=theDistance;
						}
						if(theMinimumDistance<theProfile.getIslandSpacing()){
							theCounter++;
							break;
						}
					}
					if(theCounter>TRIES_COUNTER_FAILURE_THRESHHOLD){
						throw new IslandPositionGenerationException();
					}
					if(theMinimumDistance>=theProfile.getIslandSpacing()){
						done = true;
					}
				}while(!done);
				theResult.add(theCandidate);
			}
			return theResult;
		}
		protected void onProgressUpdate(Integer... progress) {
			getClient().showPhaseProgress(progress[0]);
		}

		public CreateWorldClientStateHandler getClient() {
			return client;
		}

		private void setClient(CreateWorldClientStateHandler client) {
			this.client = client;
		}
	}

	public CreateWorldClientStateHandler(MainActivity theActivity) {
		super(theActivity);
	}

	public void showPhaseProgress(Integer theProgress) {
		ProgressBar theSlider = (ProgressBar)getActivity().findViewById(R.id.slider_progress);
		theSlider.setProgress(theProgress);
	}

	@Override
	public void handleHide() {
	}

	@Override
	public void handleButtonClick(View theView) {
		switch(theView.getId()){
		case R.id.button_cancel:
			getActivity().setState(ClientState.PLAY);
			break;
		}
	}

	@Override
	public boolean handleMenu(MenuItem theItem) {
		return false;
	}

	@Override
	public void handleShow() {
		startIslandPositionGeneration();
	}

	private void startIslandPositionGeneration() {
		Profile theProfile = getActivity().getDatabase().getProfileTableProvider().getProfileById(getActivity().getProfileId());
		ProgressBar theSlider = (ProgressBar)getActivity().findViewById(R.id.slider_progress);
		theSlider.setProgress(0);
		theSlider.setMax(theProfile.getIslandCount());
		GenerateIslandPositionsTask theTask = new GenerateIslandPositionsTask(this);
		theTask.execute(new Profile[]{theProfile});
	}

}
